package icu.zhhll.util.io;

import org.apache.commons.lang3.StringUtils;

import java.io.*;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

/**
 * zip压缩
 *
 * @author zh
 * @date 2023/8/11 10:23
 */
public class ZipUtils {


    /**
     * 多个文件压缩
     *
     * @param fromFiles
     * @param zipFilePath
     * @throws IOException
     */
    public static void toZip(List<String> fromFiles, String zipFilePath) throws IOException {

        File zipFile = new File(zipFilePath);

        try (ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFile))) {

            for (String file : fromFiles) {
                File fileWillZip = new File(file);
                if (fileWillZip.exists()) {
                    compress(fileWillZip, zipOut, fileWillZip.getName());
                }
            }

        }
    }

    private static void compress(File sourceFile, ZipOutputStream zos, String name) throws IOException {

        if (sourceFile.isFile()) {
            // 向zip输出流中添加一个zip实体，构造器中name为zip实体的文件的名字
            zos.putNextEntry(new ZipEntry(name));
            int len;
            byte[] buf = new byte[1024];
            try (FileInputStream in = new FileInputStream(sourceFile)) {
                while ((len = in.read(buf)) != -1) {
                    zos.write(buf, 0, len);
                }
                // Complete the entry
                zos.closeEntry();
            }

        } else {
            File[] listFiles = sourceFile.listFiles();
            if (listFiles == null || listFiles.length == 0) { // 空目录，只需要将空目录放入压缩包即可
                zos.putNextEntry(new ZipEntry(name + File.separator));
                zos.closeEntry();

            } else {
                for (File file : listFiles) {
                    // 递归进行压缩
                    compress(file, zos, name + File.separator + file.getName());
                }
            }
        }
    }


    /**
     * 解压
     *
     * @param source
     * @param targetDir
     * @throws IOException
     */
    public static void unZip(String source, String targetDir) throws IOException {
        if (!StringUtils.endsWith(targetDir, File.separator)) {
            targetDir = targetDir + File.separator;
        }
        try (ZipFile zipFile = new ZipFile(source)) {
            Enumeration<? extends ZipEntry> entries = zipFile.entries();
            ZipEntry ze;
            while (entries.hasMoreElements()) {
                ze = entries.nextElement();
                String zipEntryName = ze.getName();

                String outpath = (targetDir + zipEntryName).replace("/", File.separator);
                //判断路径是否存在，不存在则创建文件路径
                File file = new File(outpath.substring(0, outpath.lastIndexOf(File.separator)));
                if (!file.exists()) {
                    file.mkdirs();
                }
                //判断文件全路径是否为文件夹,如果是,不需要解压
                if (new File(outpath).isDirectory())
                    continue;

                try (InputStream in = zipFile.getInputStream(ze);
                     OutputStream out = new FileOutputStream(outpath)) {
                    byte[] bf = new byte[2048];
                    int len;
                    while ((len = in.read(bf)) > 0) {
                        out.write(bf, 0, len);
                    }
                }


            }
        }

    }

}
